﻿using System;
using MathParser.DataModel;

namespace MathParser {
    public partial class Parser {

        public string Integriere() {
            var termZusammengefasst = JoinForIntegralDifferentialCalculation(false);
            if (this.Expression != termZusammengefasst) {
                var parNew = new Parser();
                parNew.Parse(termZusammengefasst);
                return parNew.Integriere();
            }
            string term1;
            string term2;
            string ergebnis = "";
            #region Summenregel
            if (this.OpTyp == Operation.Plus) {
                term1 = this.ChildLeft.Integriere();
                term2 = this.ChildRight.Integriere();
                if ((this.ChildLeft.Error == ErrorType.Integration) || (this.ChildRight.Error == ErrorType.Integration)) {
                    Error = ErrorType.Integration;
                }
                ergebnis = term1 + "+" + term2;
            }
            else if (this.OpTyp == Operation.Minus) {
                term1 = this.ChildLeft.Integriere();
                term2 = this.ChildRight.Integriere();
                ergebnis = term1 + "-" + term2;
            }
            #endregion
            #region Potenzregel
            else if (this.OpTyp == Operation.Potenz) {
                term1 = this.ChildLeft.Expression;
                term2 = this.ChildRight.Expression;
                if ((term1 == "x") && (term2 != "x")) {
                    double expo = this.ChildRight.Caluculate(0);
                    if ((expo != 0) && (expo != -1)) {
                        string expoNeu = Convert.ToString(expo + 1);
                        AddBracketsForPlusAndMinusOperations(ref expoNeu);
                        ergebnis = "1/" + expoNeu + "*x^" + expoNeu;
                    }
                }
                else if ((term1 == "e") && (term2 == "x")) {
                    ergebnis = "e^x";
                }
                // e^(a*x) => (1/a)*e^(a*x)
                else if ((term1 == "e") && (this.ChildRight.OpTyp == Operation.Multi) &&
                    (this.ChildRight.ChildLeft.OpTyp == Operation.Zahl) && (this.ChildRight.ChildRight.Expression == "x") &&
                    (this.ChildRight.ChildLeft.Expression != "0"))
                    ergebnis = "(1/" + this.ChildRight.ChildLeft.Expression + ")*" + this.Expression;
            }
            #endregion
            #region Spezialfall Faktorregel
            else if ((this.OpTyp == Operation.Multi) && (this.ChildLeft.OpTyp == Operation.Zahl)) {
                term2 = this.ChildRight.Integriere();
                ergebnis = this.ChildLeft.Expression + "*" + term2;
            }
            #endregion
            else switch (this.OpTyp) {
                case Operation.Divi:
                    if ((this.Expression == "1/x^2") || (this.Expression == "1/(x^2)")) ergebnis = "-1/x  ";
                    break;
                case Operation.Sinus:
                    ergebnis = "-cos(x)";
                    break;
                case Operation.Cosinus:
                    ergebnis = "sin(x)";
                    break;
                case Operation.Variable:
                    ergebnis = "1/2*x^2";
                    break;
                case Operation.Zahl:
                    ergebnis = this.Expression + "*x";
                    break;
            }
            var par2 = new Parser();
            par2.Parse(ergebnis);
            string endErgebnis = par2.JoinForIntegralDifferentialCalculation(true);
            if (endErgebnis == "") {
                Error = ErrorType.Integration;
            }
            return endErgebnis;
        }
    }
}